<template>
  <AdVxeModal
    v-bind="$attrs"
    @register="register"
    :id="formIndex"
    :title="`${t('mobile.route.appVersion.title')} - ${FormModeEntityRef.Display}`"
    :help-message="`${t('common.form')}：${formIndex}`"
    :cancelText="t('common.cancelText')"
    :close-func="handleClose"
    :okText="FormModeEntityRef.OkBtnTitle"
    @ok="handleOk"
    @open-change="handleOpenChange"
    width="50%"
  >
    <BasicForm @register="registerForm" @contextmenu="handleContextMenu">
      <template #appId="{ model, field }">
        <AdChooseList
          v-model:value="model[field]"
          field="Id"
          :validate="true"
          filterField="Id"
          v-bind="getAppProps"
          :change-fn="(data) => chooseAppListChange(data)"
          :select-fn="(datas) => chooseAppListSelect(datas)"
        />
      </template>
      <template #appCode="{ model, field }">
        <AdChooseList
          v-model:value="model[field]"
          field="Code"
          :validate="true"
          filterField="Code"
          v-bind="getAppProps"
          :change-fn="(data) => chooseAppListChange(data)"
          :select-fn="(datas) => chooseAppListSelect(datas)"
        />
      </template>
      <template #appName="{ model, field }">
        <AdChooseList
          v-model:value="model[field]"
          field="Name"
          :validate="true"
          filterField="Name"
          v-bind="getAppProps"
          :change-fn="(data) => chooseAppListChange(data)"
          :select-fn="(datas) => chooseAppListSelect(datas)"
        />
      </template>
      <template #packageContent="{ model, field }">
        <UploadDragger
          v-model:value="model[field]"
          :disabled="
            FormModeEntityRef.FormMode !== FormModeEnum.Add &&
            FormModeEntityRef.FormMode !== FormModeEnum.Edit
          "
          @change="handleUploadChange"
        />
      </template>
    </BasicForm>
    <template #insertFooter>
      <Authority :value="'Root.Mobile.Admin.AppVersion.GetPackage'">
        <a-button color="success" @click="handleDownloadPackage" :loading="loadingRef">
          <Icon icon="mdi:download-circle-outline" />
          {{ t('mobile.route.appVersion.downloadPackage') }}
        </a-button>
      </Authority>
      <Authority :value="'Root.Mobile.Admin.AppVersion.SetPackage'">
        <a-button
          color="warning"
          @click="handleSetPackage"
          v-if="FormModeEntityRef.FormMode === FormModeEnum.Edit"
          :loading="loadingRef"
        >
          <Icon icon="clarity:update-line" />
          {{ t('mobile.route.appVersion.setPackage') }}
        </a-button>
      </Authority>
      <Authority :value="'Root.Mobile.Admin.AppVersion.UpdateSimple'">
        <a-button
          color="warning"
          @click="handleUpdateSimple"
          v-if="FormModeEntityRef.FormMode === FormModeEnum.Edit"
          :loading="loadingRef"
        >
          <Icon icon="clarity:note-edit-line" />
          {{ t('mobile.route.appVersion.updateSimple') }}
        </a-button>
      </Authority>
    </template>
  </AdVxeModal>

  <AdChooseListDialog @register="dialogAppRegister" v-bind="getAppDialogProps" />
  <PrintTemplateModal @register="templateModalRegister" v-bind="templateModalProps" />
</template>

<script lang="ts" setup>
  import type { PropType } from 'vue';
  import { ref } from 'vue';

  import { UploadDragger } from '@/components/UploadDragger';
  import { Authority } from '@/components/Authority';
  import { AdVxeModal, useModalInner } from '@/components/AdVxeModal';
  import { BasicForm } from '@/components/Form';
  import { PrintTemplateModal, useAdPrint } from '@/components/AdPrint';
  import Icon from '@/components/Icon/Icon.vue';

  import { useI18n } from '@/hooks/web/useI18n';
  import { useContextMenu } from '@/hooks/web/useContextMenu';
  import { destroyContextMenu } from '@/components/ContextMenu';
  import { isFunction } from '@/utils/is';
  import { downloadByBase64 } from '@/utils/file/download';

  import { FormModeEnum, FormModeEntity } from '@/enums/formEnum';

  import { AjaxResult } from '#/request';
  import { AppVersionInputDto, AppVersionOutputDto } from '@/api/mobile/model/appversion';
  import { AppPackageInputDto } from '@/api/mobile/model/apppackage';
  import {
    createAppVersion,
    updateAppVersion,
    deleteAppVersion,
    updateAppVersionSimple,
    getAppPackage,
    setAppPackage,
  } from '@/api/mobile/admin/appversion';

  import { useAppChooseList } from '@/api/mobile';

  import { registerForm, resetFields, getFieldsValue, setFieldsValue, validate } from './detail';

  defineOptions({ name: 'MobAppVersionDetailModal' });
  const props = defineProps({
    /** 关闭回调，返回true关闭窗体 */
    closeFunc: {
      type: Function as PropType<
        (formMode: FormModeEnum, record?: AppVersionOutputDto) => Promise<boolean>
      >,
      default: null,
    },
    /** 提交前回调，返回false不执行内置提交逻辑，返回true执行内置提交逻辑 */
    beforeSubmitFunc: {
      type: Function as PropType<
        (formMode: FormModeEnum, record?: AppVersionOutputDto) => Promise<boolean>
      >,
      default: null,
    },
    /** 提交后回调，返回true关闭窗体 */
    afterSubmitFunc: {
      type: Function as PropType<
        (
          formMode: FormModeEnum,
          result?: AjaxResult | null,
          record?: AppVersionOutputDto,
        ) => Promise<boolean>
      >,
      default: null,
    },
  });

  const { t } = useI18n();
  const [createContextMenu] = useContextMenu();
  const formIndex = 'ea_mobild_appversion_detail';
  const keyField = 'Id';

  const formModeRef = ref<FormModeEnum>(FormModeEnum.Ok);
  const FormModeEntityRef = ref<FormModeEntity>(new FormModeEntity(formModeRef.value));

  const [register, { setModalProps, closeModal, changeLoading }] = useModalInner(async (data) => {
    changeLoading(true);
    try {
      await clearInputDto();
      let record = (data?.record || {}) as AppVersionOutputDto;
      if (data.formMode) {
        formModeRef.value = data.formMode as FormModeEnum;
        FormModeEntityRef.value = new FormModeEntity(formModeRef.value);
        switch (formModeRef.value) {
          case FormModeEnum.Add:
            break;
          case FormModeEnum.Edit:
          case FormModeEnum.ReadOnly:
          case FormModeEnum.Ok:
            if (record?.Id) {
              const result = await getAppPackage(record.Id);
              if (result) {
                const packageOutputDto = result;
                // console.log(packageOutputDto);
                if (packageOutputDto) {
                  record = { ...record, Package: { ...packageOutputDto } };
                }
              }
            }

            break;
        }
      }
      if (record) {
        await setInputDto({
          ...record,
        });
      }
    } finally {
      changeLoading(false);
    }
  });

  //#region "加载状态"
  const loadingRef = ref(false);
  /** 开启加载状态 */
  function openLoading() {
    changeLoading(true);
    setModalProps({ okLoading: true, cancelLoading: true });
    loadingRef.value = true;
  }
  /** 关闭加载状态 */
  function closeLoading() {
    changeLoading(false);
    setModalProps({ okLoading: false, cancelLoading: false });
    loadingRef.value = false;
  }
  //#endregion
  //#region 定义高级打印
  const { printContextMenus, templateModalRegister, templateModalProps } = useAdPrint({
    formIndex: formIndex,
    keyField: keyField,
    getFormData: () => getInputDto(),
  });
  /** 处理上下文菜单(右键菜单) */
  function handleContextMenu(e: MouseEvent) {
    const element = document.elementFromPoint(e.clientX, e.clientY) as Element;
    const cursor = document.defaultView?.getComputedStyle(element, null).cursor;
    // console.log('handleContextMenu', {
    //   cursor: cursor,
    // });

    let items: any[] = [];
    switch (FormModeEntityRef.value.FormMode) {
      case FormModeEnum.Ok:
      case FormModeEnum.Edit:
      case FormModeEnum.ReadOnly:
        if (!cursor || cursor === 'default' || cursor === 'auto') {
          items = [...printContextMenus];
        }
        break;
    }
    if (items && items?.length > 0) {
      createContextMenu({
        event: e,
        styles: {
          border: '1px solid #eee',
          'border-radius': '2px',
          'box-shadow': '3px 3px 3px rgb(0 0 0 / 15%)',
        },
        items: [...items],
      });
    }
  }
  //#endregion

  //#region "移动端应用选择"
  const {
    AdChooseList,
    AdChooseListDialog,
    dialogRegister: dialogAppRegister,
    getDialogProps: getAppDialogProps,
    getProps: getAppProps,
  } = useAppChooseList();
  /** 高级选择列表更改事件 */
  async function chooseAppListChange(data: Recordable) {
    const { record } = data;
    await setInputDto({
      AppId: record.Id,
      AppCode: record.Code,
      AppPlatform: record.Platform,
      AppName: record.Name,
      Author: record.Author,
      Email: record.Email,
      PhoneNumber: record.PhoneNumber,
    });
  }
  /** 高级选择列表选择事件 */
  async function chooseAppListSelect(datas: Recordable[]) {
    if (datas?.length > 0) {
      const data = datas[0];
      await setInputDto({
        AppId: data.Id,
        AppCode: data.Code,
        AppPlatform: data.Platform,
        AppName: data.Name,
        Author: data.Author,
        Email: data.Email,
        PhoneNumber: data.PhoneNumber,
      });
      return true;
    } else {
      return false;
    }
  }
  //#endregion

  /** 获取输入DTO */
  function getInputDto(): AppVersionInputDto {
    const record = getFieldsValue() as AppVersionInputDto;
    if (record.Package) {
      record.Package.VersionId = record.Id;
    }
    return record;
  }
  /** 设置输入DTO */
  async function setInputDto(values: any) {
    let inputDto = getInputDto();
    inputDto = { ...inputDto, ...values };
    await setFieldsValue({ ...inputDto });
  }
  /** 清除输入DTO */
  async function clearInputDto() {
    await resetFields();
  }

  /** 获取输出DTO */
  function getOutputDto(): AppVersionOutputDto {
    const record = getFieldsValue() as AppVersionOutputDto;
    return record;
  }

  /** 文件上传触发 */
  async function handleUploadChange({ value, fileInfo }) {
    // console.log('handleUploadChange', { value, fileInfo });
    if (value && fileInfo) {
      let inputDto = getInputDto();
      inputDto.Package = {
        ...inputDto.Package,
        Name: fileInfo.name,
        Content: value,
      } as AppPackageInputDto;
      await setInputDto(inputDto);
    }
  }

  /** 处理关闭按钮 */
  async function handleClose() {
    openLoading();

    const { closeFunc } = props;
    try {
      if (closeFunc && isFunction(closeFunc)) {
        const outputDto = getOutputDto();
        const result = await closeFunc(FormModeEntityRef.value.FormMode, outputDto);
        return result;
      }
    } finally {
      closeLoading();
    }
    return true;
  }
  /** 处理确定按钮 */
  async function handleOk() {
    const data = await validate();
    if (!data) return;
    //console.log(data);

    openLoading();
    const { beforeSubmitFunc, afterSubmitFunc } = props;
    try {
      const inputDto = getInputDto();
      const outputDto = getOutputDto();
      // console.log('handleOk', inputDto);
      let innerSubmit = true;
      let innerCloseModal = true;
      if (beforeSubmitFunc && isFunction(beforeSubmitFunc)) {
        innerSubmit = await beforeSubmitFunc(FormModeEntityRef.value.FormMode, outputDto);
      }
      let result: AjaxResult | null = null;
      if (innerSubmit) {
        switch (FormModeEntityRef.value.FormMode) {
          case FormModeEnum.Add:
            result = await createAppVersion([inputDto]);
            break;
          case FormModeEnum.Edit:
            result = await updateAppVersion([inputDto]);
            break;
          case FormModeEnum.Delete:
            result = await deleteAppVersion([inputDto.Id]);
            break;
        }
      }
      if (afterSubmitFunc && isFunction(afterSubmitFunc)) {
        innerCloseModal = await afterSubmitFunc(
          FormModeEntityRef.value.FormMode,
          result,
          outputDto,
        );
      }
      if (innerCloseModal) {
        closeModal();
      }
    } finally {
      closeLoading();
    }
  }

  /** 处理设置程序包 */
  async function handleDownloadPackage() {
    openLoading();
    try {
      const inputDto = getInputDto();
      // console.log('inputDto', inputDto);
      if (inputDto?.Package?.Name && inputDto?.Package?.Content) {
        downloadByBase64(inputDto.Package.Content, inputDto.Package.Name);
      }
    } finally {
      closeLoading();
    }
  }
  /** 处理设置程序包 */
  async function handleSetPackage() {
    const { afterSubmitFunc } = props;
    if (FormModeEntityRef.value.FormMode === FormModeEnum.Edit) {
      openLoading();
      try {
        const inputDto = getInputDto();
        const outputDto = getOutputDto();
        let packageDto = inputDto.Package || ({} as AppPackageInputDto);
        packageDto.VersionId = inputDto.Id;
        // console.log('handleOk', inputDto);
        let innerCloseModal = true;
        var reulst = await setAppPackage([packageDto]);
        if (afterSubmitFunc && isFunction(afterSubmitFunc)) {
          innerCloseModal = await afterSubmitFunc(
            FormModeEntityRef.value.FormMode,
            reulst,
            outputDto,
          );
        }
        if (innerCloseModal) {
          closeModal();
        }
      } finally {
        closeLoading();
      }
    }
  }
  /** 处理更新驱动简单信息 */
  async function handleUpdateSimple() {
    const data = await validate();
    if (!data) return;

    const { afterSubmitFunc } = props;
    if (FormModeEntityRef.value.FormMode === FormModeEnum.Edit) {
      openLoading();
      try {
        const inputDto = getInputDto();
        const outputDto = getOutputDto();
        // console.log('handleOk', inputDto);
        let innerCloseModal = true;
        var reulst = await updateAppVersionSimple([inputDto]);
        if (afterSubmitFunc && isFunction(afterSubmitFunc)) {
          innerCloseModal = await afterSubmitFunc(
            FormModeEntityRef.value.FormMode,
            reulst,
            outputDto,
          );
        }
        if (innerCloseModal) {
          closeModal();
        }
      } finally {
        closeLoading();
      }
    }
  }

  /** 打开或者关闭触发 */
  function handleOpenChange(open: boolean) {
    if (!open) {
      destroyContextMenu();
    }
  }
</script>

<style lang="less" scoped>
  .qr-code {
    margin: 0 auto;
    margin-bottom: 15px;
    text-align: center;
  }

  .context-menu {
    z-index: 8888 !important;
  }
</style>
